package com.cci.kangdao.service.impl;

import com.auth0.jwt.interfaces.DecodedJWT;
import com.cci.kangdao.azureAD.AzureADTool;
import com.cci.kangdao.cipapi.CipServiceApi;
import com.cci.kangdao.common.RedisKeys;
import com.cci.kangdao.dao.*;
import com.cci.kangdao.dao.model.*;
import com.cci.kangdao.dto.request.AKeyLoginRequest;
import com.cci.kangdao.dto.request.PerfectAccountMessageRequest;
import com.cci.kangdao.externalData.dto.request.LyhFileUserRequest;
import com.cci.kangdao.externalData.service.ExternalDataSynchroService;
import com.cci.kangdao.redis.RedisClientUtils;
import com.cci.kangdao.service.AKeyLoginService;
import com.cci.kangdao.service.InviteUserService;
import com.cci.kangdao.utilTool.*;
import com.gexin.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.security.interfaces.RSAPrivateKey;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * @author linjiankun
 * @date 2022/6/10 9:47
 */
@Service("AKeyLoginService")
public class AKeyLoginServiceImpl implements AKeyLoginService {

    private Logger log = Logger.getLogger(this.getClass().getName());
    @Autowired
    private RedisClientUtils redisClientUtils;
    @Resource
    private AKeyLoginUserTokenDao aKeyLoginUserTokenDao;
    @Resource
    private LoginDao loginDao;
    @Resource
    private RolesServiceImpl rolesService;
    @Resource
    private UserTokenTMapper userTokenTMapper;
    @Resource
    private UserTDao userTDao;
    @Resource
    private UserLabelMapper userLabelMapper;
    @Resource
    private ServiceStationDao serviceStationDao;
    @Resource
    private InviteUserService inviteUserService;
    @Resource
    private WAMdrtDao waMdrtDao;
    @Resource
    private CipServiceApi cipServiceApi;
    @Resource
    private ExternalDataSynchroService externalDataSynchroService;

    @Value("${TIANYIAPPID}")
    private String TIANYIAPPID;
    @Value("${TIANYIAPPSecret}")
    private String TIANYIAPPSecret;
    @Value("${redisCacheTime}")
    private String redisCacheTime;
    @Value("${redisAKeyLoginTokenCacheTime}")
    private String redisAKeyLoginTokenCacheTime;
    @Value("${RSAPrivateKeyStr}")
    private String RSAPrivateKeyStr;
    @Value("${sdkcodeinfoUrl}")
    private String sdkcodeinfoUrl;
    @Value("${webClient_id}")
    private String webClient_id;
    @Value("${webClientSecret}")
    private String webClientSecret;
    @Value("${tenant}")
    private String tenant;
    @Value("${userPhotoUrl}")
    private String userPhotoUrl;

    //一键登录成功  更新ad token  增加的前缀
    private static final String startsWithAKeyLogin = "aKeyLogin--------";
    //用户使用用户名密码或wwid方式登录   更新local token  增加的前缀
    private static final String startsWithAdTokenLogin = "adTokenLogin--------";
    Pattern p = Pattern.compile("^1[3456789]\\d{9}$");

    @Override
    @Transactional
    public ModelAndView aKeyLogin(String paramStr, HttpServletRequest request,
                                                   HttpServletResponse response) throws Exception {
        log.info("aKeyLogin.aspx接口入参paramStr："+paramStr);
        JSONObject obj = new JSONObject();
        //响应的data数据
        Map<String,Object> returnMap = new HashMap<>();
        //1.提取参数信息
        AKeyLoginRequest aKeyLoginRequest = JSON.parseObject(paramStr, AKeyLoginRequest.class);
        //2.校验参数是否必填
        Integer requestType = aKeyLoginRequest.getRequestType();
        String accessCode = aKeyLoginRequest.getAccessCode();
        String authCode = aKeyLoginRequest.getAuthCode();
        String cellPhone = aKeyLoginRequest.getCellPhone();
        String verifyCode = aKeyLoginRequest.getVerifyCode();
        String referralCode = aKeyLoginRequest.getReferralCode();
        if(null == requestType || requestType == -1 || (requestType != 0 && requestType != 1)){
            ParameterTool.writeResponse(response, 17,"缺少必要参数或所传参数非枚举值！");
            return null;
        }
        if(requestType == 0 && (StringUtils.isEmpty(accessCode) || StringUtils.isEmpty(authCode))){
            ParameterTool.writeResponse(response, 17,"缺少必要参数！");
            return null;
        }
        if(requestType == 1 && (StringUtils.isEmpty(cellPhone) || StringUtils.isEmpty(verifyCode))){
            ParameterTool.writeResponse(response, 17,"缺少必要参数！");
            return null;
        }
        if(requestType == 1){
            String redisVerifyCode = redisClientUtils.get(RedisKeys.aKeyLoginCellPhoneVerifyCodeKey(cellPhone));
            if (StringUtils.isEmpty(redisVerifyCode)) {
                ParameterTool.writeResponse(response, -6, "验证码错误，请重新输入！");
                return null;
            }
            Object typeLock = redisClientUtils.getObject(RedisKeys.aKeyLoginCellPhoneVerifyCodeKey(cellPhone) + "-lock");
            if (null != typeLock) {
                com.alibaba.fastjson.JSONObject jsonObject = com.alibaba.fastjson.JSONObject.parseObject(typeLock.toString());
                Integer locktimeRedis = jsonObject.getInteger("locktime");
                String currentDate = jsonObject.getString("currentDate");
                boolean before = LocalTimeUtil.isBefore(LocalTimeUtil.getTimeAfterSeconds(currentDate, locktimeRedis * 60), LocalTimeUtil.getRealCurrentTime());
                if (!before) {
                    redisClientUtils.delkey(RedisKeys.aKeyLoginCellPhoneVerifyCodeKey(cellPhone));
                    ParameterTool.writeErrorResponse(response, -55, "您已连续输错多次，请" + LocalTimeUtil.turnDayHourMinuteString((int) locktimeRedis) + "后再试！");
                    return null;
                }
            }

            if (!verifyCode.equals(redisVerifyCode)) {

                String times = (String) redisClientUtils.get(RedisKeys.aKeyLoginCellPhoneVerifyCodeKey(cellPhone) + "smsTimes");
                int timeInt = 0;
                int timeMax = 5;
                if (org.apache.commons.lang3.StringUtils.isNotBlank(times)) {
                    timeInt = Integer.valueOf(times);
                }
                int timesV = timeInt + 1;
                if (timesV < timeMax) {
                    redisClientUtils.set(RedisKeys.aKeyLoginCellPhoneVerifyCodeKey(cellPhone) + "smsTimes", String.valueOf(timesV), 0);
                    ParameterTool.writeResponse(response, -6, "验证码错误，请重新输入！");
                    return null;
                } else {
                    int locktime = 5;
                    Object type = redisClientUtils.getObject(RedisKeys.aKeyLoginCellPhoneVerifyCodeKey(cellPhone) + "-lock");
                    if (null != type) {
                        com.alibaba.fastjson.JSONObject jsonObject = com.alibaba.fastjson.JSONObject.parseObject(type.toString());
                        Integer locktimeRedis = jsonObject.getInteger("locktime");
                        locktime = 2 * locktimeRedis;
                    }
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("locktime", locktime);
                    jsonObject.put("currentDate", LocalTimeUtil.getRealCurrentTime());
                    redisClientUtils.setObject(RedisKeys.aKeyLoginCellPhoneVerifyCodeKey(cellPhone) + "-lock", jsonObject, 0);
                    redisClientUtils.delkey(RedisKeys.aKeyLoginCellPhoneVerifyCodeKey(cellPhone));
                    if (timesV == 5) {
                        ParameterTool.writeErrorResponse(response, -55);
                        return null;
                    } else {
                        ParameterTool.writeErrorResponse(response, -55, "您已连续输错多次，请" + LocalTimeUtil.turnDayHourMinuteString(locktime) + "后再试！");
                        return null;
                    }
                }

            } else {
                redisClientUtils.delkey(RedisKeys.aKeyLoginCellPhoneVerifyCodeKey(cellPhone) + "smsTimes");
                redisClientUtils.delkey(RedisKeys.aKeyLoginCellPhoneVerifyCodeKey(cellPhone) + "-lock");
                redisClientUtils.delkey(RedisKeys.aKeyLoginCellPhoneVerifyCodeKey(cellPhone));
            }
        }
        String phone = "";
        if(requestType == 1){
            phone = cellPhone;
        }else{
            //3.调用sdk授权接口  获取手机号
            //毫秒级时间戳
            long timestamp = LocalTimeUtil.getRealTimestamp();
            String data = "accessCode="+accessCode+"&authCode="+authCode;
            byte[] encBytes = XXTEAUtil.encrypt(data.getBytes("UTF-8"), TIANYIAPPSecret.getBytes("UTF-8"));
            String params = ByteFormat.bytesToHexString(encBytes);
            //加载私钥
            RSAPrivateKey loadPrivateKey = RSAUtil.loadPrivateKey(RSAPrivateKeyStr);
            //待签名数据
            String content = TIANYIAPPID+"json"+params+timestamp;
            //RSA加密
            String sign = RSAUtil.sign(content,loadPrivateKey);
            Map<String,Object> requestMap = new HashMap<>();
            requestMap.put("appId",TIANYIAPPID);
            requestMap.put("format","json");
            requestMap.put("sign",sign);
            requestMap.put("timeStamp",timestamp);
            requestMap.put("params",params);

            log.info("一键登录调用电信天翼sdk授权接口，请求参数："+requestMap);
            String requestResult = HttpClient.doPost(sdkcodeinfoUrl, requestMap);
            log.info("一键登录调用电信天翼sdk授权接口，返回结果："+requestResult);
            net.sf.json.JSONObject jsb = net.sf.json.JSONObject.fromObject(requestResult);
            int result = jsb.getInt("result");
            if(0 == result && StringUtils.isNotEmpty(jsb.getString("data"))){
                String finalData = RSAUtil.decrypt(RSAUtil.loadPrivateKey(RSAPrivateKeyStr), jsb.getString("data"));
                log.info("一键登录调用电信天翼sdk授权接口，返回结果解密后："+finalData);
                net.sf.json.JSONObject jsonObject = net.sf.json.JSONObject.fromObject(finalData);
                phone = jsonObject.getString("mobile");
                if(StringUtils.isEmpty(phone)){
                    ParameterTool.writeResponse(response, -18,"一键登录后台调用sdk接口成功，但未获取到手机用户信息，请重试！");
                    return null;
                }
            }else{
                if(0 == result && StringUtils.isEmpty(jsb.getString("data"))){
                    ParameterTool.writeResponse(response, -18,"一键登录后台调用sdk接口成功，但未获取到响应data信息，请重试！");
                }else{
                    String msg = jsb.getString("msg");
                    ParameterTool.writeResponse(response, result,msg);
                }
                return null;
            }
        }
        // 加锁处理，避免发生多次提交。
        String lockKey= "aKeyLogin-" + phone ;
        if (!redisClientUtils.lock(lockKey, 60L)) {
            //防止并发
            ParameterTool.writeErrorResponse(response, -98);
            return null;
        }
        try {
            //4.判断是否是系统用户   //跟产品确认过一键登录，他人号码登录的手机号和系统中的UserName字段匹配，匹配上的就是存在，反之不存在
            UserT userT = loginDao.getUserTByUserName(phone);
            int isInitInfo = 1;  //是否完善过信息   0：否   1：是（登录后是否填写并提交账户信息）
            int isMillionRelation = 0;
            //String aKeyLoginUserTRedisKey = "AKeyLogin-UserT-" + phone;
            if(null == userT){
                //注册用户为终端用户
                userT = new UserT();
                userT.setPhone(phone);
                //sprint52   jira：CDAP-4948 一键登录注册用户时   将手机号赋值到姓名字段
                userT.setContact(phone);
                userT.setUserSource(3);
                userT.setReferralCode(referralCode);
                /*
                    sprint58 【IP地址解析】通过IP现有注册IP解析用户的地区  jira 5998
                */
                //获取请求的ip
                String ip = RequestIPUtils.getRequestClientRealIp(request);
                //通过IP获取 地区
                userT = GDRegion.addProviceAndCity(ip, userT);
                boolean isSuccess = registerEndUser(response, userT);
                isInitInfo = 0;
                if (!isSuccess) {
                    return null;
                }
                //是否新注册用户   0：否   1：是
                returnMap.put("isNewRegister", 1);
                //验证是否百万圆桌邀请
                isMillionRelation = waMdrtDao.getInviteUserCount(userT.getPhone(), userT.getId(), userT.getUserName());

                //根据邀请码 添加邀请用户关系
                inviteUserService.addInsertByCode(userT.getId(),phone,referralCode);
            }else{
                Integer userType = userT.getType();
                if(2 == userType){
                    ParameterTool.writeResponse(response,2,"");
                    return null;
                }
                UserTokenT userTokenT = userTokenTMapper.selectByUserId(userT.getId());
                if(null != userTokenT && !userTokenT.getAccessToken().startsWith(startsWithAKeyLogin)){
                    //清除用户之前的缓存数据  保证同一个账户不同登录方式互踢
                    redisClientUtils.delkey("userT" + userT.getId());
                    redisClientUtils.delkey(RedisKeys.tokenKey(userTokenT.getAccessToken()));
                    //修改原来的ad adtoken值   保证互踢
                    userTokenT.setAccessToken(startsWithAKeyLogin + userTokenT.getAccessToken());
                    userTokenTMapper.updateByPrimaryKeySelective(userTokenT);
                }
                //用户来源 默认为0:e路康明斯注册用户，1:三兄弟注册用户，2:微信公众号注册用户 3.本机一键登录注册用户 4.他人号码一键登录注册用户
                if (userT.getUserSource() == 3 || userT.getUserSource() == 4) {
                    isInitInfo = userT.getIsInitInfo();
                }
                //是否新注册用户   0：否   1：是
                returnMap.put("isNewRegister", 0);
                //验证是否百万圆桌邀请
                isMillionRelation = waMdrtDao.getInviteUserCount(userT.getPhone(), userT.getId(), userT.getUserName());

                inviteUserService.addMdrtInsertByCode(userT.getId(), phone, referralCode);
                /*
                sprint58 【IP地址解析】通过IP现有注册IP解析用户的地区  jira 5998
                 */
                if (org.apache.commons.lang3.StringUtils.isBlank(userT.getProvince()) &&
                        org.apache.commons.lang3.StringUtils.isBlank(userT.getCity()) &&
                        org.apache.commons.lang3.StringUtils.isBlank(userT.getIp())) {
                    String ip = RequestIPUtils.getRequestClientRealIp(request);
                    //通过ip获取省市
                    userT = GDRegion.addProviceAndCity(ip, userT);
                    userTDao.updateCityAndproviceSelective(userT);
                }
            }
            returnMap.put("isMillionRelation",isMillionRelation);
            returnMap.put("initInfo",isInitInfo);
            redisClientUtils.setObject("userT" + userT.getId(), userT, Integer.valueOf(redisCacheTime));
            //5.获取local token
            String localToken = JWTTool.getToken(phone);
            //6.将local token保存到redis和AKeyLoginUserTokenT表中
            String currentTime = LocalTimeUtil.getRealCurrentTime();
            AKeyLoginUserTokenT aKeyLoginUserTokenMsg = aKeyLoginUserTokenDao.getAKeyLoginUserTokenByUserId(userT.getId(),1);
            if(null != aKeyLoginUserTokenMsg){  //重新更新token
                aKeyLoginUserTokenMsg.setLocalToken(localToken);
                //两小时过期
                aKeyLoginUserTokenMsg.setExpireTime(LocalTimeUtil.getTimeAfter(currentTime,2));
                aKeyLoginUserTokenMsg.setUpdator(userT.getId());
                aKeyLoginUserTokenMsg.setUpdateTime(currentTime);
                aKeyLoginUserTokenDao.updateSelective(aKeyLoginUserTokenMsg);
            }else{  //新增一条token
                aKeyLoginUserTokenMsg = new AKeyLoginUserTokenT();
                aKeyLoginUserTokenMsg.setUserId(userT.getId());
                aKeyLoginUserTokenMsg.setLocalToken(localToken);
                //1代表一键登录token
                aKeyLoginUserTokenMsg.setType(1);
                //两小时过期
                aKeyLoginUserTokenMsg.setExpireTime(LocalTimeUtil.getTimeAfter(currentTime,2));
                aKeyLoginUserTokenMsg.setCreator(userT.getId());
                aKeyLoginUserTokenMsg.setCreateTime(currentTime);
                aKeyLoginUserTokenDao.insertSelective(aKeyLoginUserTokenMsg);
            }
            redisClientUtils.setObject(RedisKeys.localTokenKey(phone),aKeyLoginUserTokenMsg,Integer.valueOf(redisAKeyLoginTokenCacheTime));

            returnMap.put("userid",userT.getId()+"");
            returnMap.put("adUserId",userT.getAduserId());
            returnMap.put("token",localToken);
            returnMap.put("isPwd",userT.getIsPwd());
            //0:app原生    1:微信公众号      2:本机号码一键登录和手机号验证码一键登录
            returnMap.put("tokenType",2);
            returnMap.put("phone",phone);
            SystemLogsT systemLogsT = new SystemLogsT();
            systemLogsT.setUserId(userT.getId());
            systemLogsT.setTname("aKeyLogin");
            systemLogsT.setTid(0);
            systemLogsT.setActionName("aKeyLogin");
            if(0 == requestType){
                systemLogsT.setRemark("一键登录");
            }else{
                systemLogsT.setRemark("手机号验证码登录");
            }
            loginDao.insertSystemLogs(systemLogsT);
            obj.put("data",returnMap);
            obj.put("status", 0);
            obj.put("msg", "success");
        } catch (Exception e) {
            log.error(e.getMessage(),e);
            String msg = "{\"status\": -99,\"msg\": \"未知错误\"}";
            ParameterTool.writeResponse(response, msg);
        }finally {
            //释放锁
            redisClientUtils.delkey(lockKey);
        }
        ParameterTool.writeResponse(response, obj.toString());
        return null;
    }


    /**
     * 注册用户角色为终端用户
     * phone 一键登录用户手机号
     * userSource  用户来源 默认为0:e路康明斯注册用户，1:三兄弟注册用户，2:微信公众号注册用户 3.本机一键登录注册用户 4.他人号码一键登录注册用户
     */
    public boolean registerEndUser(HttpServletResponse response,UserT userT){
        boolean isSuccess = true;
        //获取token
        String token = AzureADTool.getManagementToken(tenant, webClient_id, webClientSecret);
        if (null == token) {
            ParameterTool.writeErrorResponse(response);
            isSuccess = false;
        }
        //生成8位随机密码  需要规避字母：i/I/o/O/l    数字：1/0
        String pwd = NumberUtils.getStringRandom(8);

        String userJson = AzureADTool.getUser(userT.getPhone(), tenant, token);
        if (org.apache.commons.lang3.StringUtils.isEmpty(userJson)) {
            // 2、Azure AD使用token去新建用户
            userJson = AzureADTool.addUser(userT.getPhone(), pwd, tenant, token);
            if (org.apache.commons.lang3.StringUtils.isEmpty(userJson)) {
                ParameterTool.writeErrorResponse(response);
                isSuccess = false;
            }
        }


        /**
         * 3、保存用户数据到数据库
         *  并给用户添加默认用户组、子用户组、角色
         */
        JSONObject jsonObj = null;
        try {
            jsonObj = new JSONObject(userJson);
            String adUserId = jsonObj.getString("id");
            //插入用户数据
            userT.setAduserId(adUserId);
            userT.setUserName(userT.getPhone());
            //userT.setContact(userT.getPhone());
            userT.setAzureToken("");
            userT.setPhone(userT.getPhone());
            userT.setContact(userT.getPhone());
            userT.setIsPwd(0);
            userT.setType(1);
            if (StringUtils.isBlank(userT.getEmail())) {
                userT.setEmail("");
            }
            userT.setEmployeeNum("");
            userT.setPhotoUrl(userPhotoUrl);
            //userT.setSystime(LocalTimeUtil.getRealCurrentTime());
            //获取用户组
            userT = rolesService.initBaseUserGroup(userT);
            int flag = loginDao.insertUserNew(userT);
            if (flag <= 0) {
                //返回客户
                ParameterTool.writeErrorResponse(response, -99);
                isSuccess = false;
            }
            //修改用户来源字段
            //用户来源(默认为0:e路康明斯注册用户，1:三兄弟注册用户，2:微信公众号注册用户 3.本机一键登录注册用户 4.他人号码一键登录注册用户
            int num = loginDao.updateUserSourceById(userT.getUserSource(), userT.getId());
            rolesService.initBaseRoles(userT);

            //添加新手活动
            log.info("添加新手活动；userId:" + userT.getId());
            cipServiceApi.addNeophyteUser(userT.getId());
            //注册时接收老友会用户
            LyhFileUserRequest userRequest = new LyhFileUserRequest();
            userRequest.setUserId(userT.getId());
            userRequest.setPhone(userT.getPhone());
            externalDataSynchroService.receiveLyhUser(userRequest);
        } catch (JSONException e) {
            log.error("一键登录用户注册异常，注册用户：" + userT.getPhone() + e.getMessage(),e);
        }
        return isSuccess;
    }

    /**
     * 通过手机号发送验证码   应用于手机号码验证码登录使用
     * @param map
     * @return
     */
    @Override
    public ModelAndView aKeyLoginSendVerifyCode(Map map) {
        HttpServletRequest request = (HttpServletRequest) map.get("request");
        HttpServletResponse response = (HttpServletResponse) map.get("response");
        // 1.数据校验
        String mobile = MapUtils.getString(map,"mobile","");
        log.info("通过手机号发送验证码，应用于手机号码验证码登录使用，当前手机号为" + mobile + "-----------");
        if (StringUtils.isEmpty(mobile)) {
            ParameterTool.writeErrorResponse(response, -5);
            return null;
        }
        Matcher matcher = p.matcher(mobile);
        if (!matcher.matches()) {
            ParameterTool.writeErrorResponse(response, -47);
            return null;
        }

        // 加锁处理，避免发生多次提交。
        String lockKey= "aKeyLoginSendVerifyCode-" + mobile ;
        if (!redisClientUtils.lock(lockKey, 60L)) {
            //防止并发
            ParameterTool.writeErrorResponse(response, -48);
            return null;
        }
        try {
            HttpSession session = request.getSession(false);
            if (session != null) {
                session.invalidate();
            }
            request.getSession(true);
            /**
             * 生成验证吗
             */
            String smsCode = PublicTool.getFourRandom();
            log.info("您的验证码是" + smsCode);
            redisClientUtils.set(RedisKeys.aKeyLoginCellPhoneVerifyCodeKey(mobile) , smsCode, 90); //1分钟有效,但是实际是时间太短
            /**
             * 发送短信
             */
            String smstext = "您此次的验证码为{验证码}，有效期1分钟，请输入后进行验证，谢谢！";
            String reuslt = SmsUtils.sendMessageNotTD(mobile, smstext.replace("{验证码}", smsCode));
            ParameterTool.writeSuccessResponse(response);
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
            ParameterTool.writeErrorResponse(response);
        }
        return null;
    }



    /**
     * 一键登录或他人号码验证登录用户刷新local token接口
     * @param map
     * @return
     */
    public ModelAndView refreshLocalToken(Map map) {
        HttpServletRequest request = (HttpServletRequest) map.get("request");
        HttpServletResponse response = (HttpServletResponse) map.get("response");
        try {
            // 1.数据校验 通过userId和token来获取数据并校验正确性
            String token = request.getHeader("Authorization");
            String userId = request.getHeader("userid");
            log.info("刷新本地token接口，接口头信息userId：" + userId +",接口头信息Authorization："+token);
            if (StringUtils.isEmpty(token) || StringUtils.isEmpty(userId)) {
                ParameterTool.writeErrorResponse(response, -5);
                return null;
            }
            userId = AESTool.decryptString(userId);
            if(!NumberUtils.isDigits(userId)){
                ParameterTool.writeErrorResponse(response, -1);
                return null;
            }
            long userID = Long.parseLong(userId);
            UserT userT = loginDao.getUserMsgById(userID);
            if(null == userT){
                ParameterTool.writeErrorResponse(response, -18);
                return null;
            }
            DecodedJWT decodedJWT = JWTTool.getDecodedJWTByToken(token);
            if(null == decodedJWT || null == decodedJWT.getClaim("username")){
                ParameterTool.writeErrorResponse(response, -1);
                return null;
            }
            String username = decodedJWT.getClaim("username").asString();
            if(StringUtils.isEmpty(username) || (StringUtils.isNotEmpty(username) && !userT.getUserName().equals(username) && !userT.getPhone().equals(username))){
                ParameterTool.writeErrorResponse(response, -1);
                return null;
            }
            // 先获取缓存中的token
            AKeyLoginUserTokenT aKeyLoginUserTokenT = (AKeyLoginUserTokenT) redisClientUtils.getObject(RedisKeys.localTokenKey(userT.getPhone()));
            if (null == aKeyLoginUserTokenT) {
                // 缓存中不存在token信息，再通过用户信息获取数据库中token信息
                aKeyLoginUserTokenT = aKeyLoginUserTokenDao.getAKeyLoginUserTokenByUserId(userID,1);
            }

            if (null == aKeyLoginUserTokenT) {
                //无法找到token相关信息
                ParameterTool.writeErrorResponse(response, -1);
                return null;
            } else {
                log.info("当前用户username是："+ userT.getUserName() +"头信息Authorization解密后username是："+username);
                // localtoken在有效期并且没有被更新过
                if (LocalTimeUtil.isBefore(LocalTimeUtil.getRealCurrentTime(), aKeyLoginUserTokenT.getExpireTime())
                && !aKeyLoginUserTokenT.getLocalToken().startsWith(startsWithAdTokenLogin)) {
                    ParameterTool.writeSuccessResponse(response, aKeyLoginUserTokenT.getLocalToken());
                    return null;
                } else {
                    // localtoken不在有效期或者被更新过，则重新生成local token
                    String localToken = JWTTool.getToken(userT.getUserName());
                    // 新token不为空，返回前端
                    if (StringUtils.isNotEmpty(localToken)) {
                        ParameterTool.writeSuccessResponse(response, localToken);
                    } else {
                        // 新token为空，说明生成新local token出现问题
                        ParameterTool.writeErrorResponse(response, -1);
                        return null;
                    }
                    //更新local token
                    String currentTime = LocalTimeUtil.getRealCurrentTime();
                    aKeyLoginUserTokenT.setLocalToken(localToken);
                    //两小时过期
                    aKeyLoginUserTokenT.setExpireTime(LocalTimeUtil.getTimeAfter(currentTime,2));
                    aKeyLoginUserTokenT.setUpdator(userT.getId());
                    aKeyLoginUserTokenT.setUpdateTime(currentTime);
                    aKeyLoginUserTokenDao.updateSelective(aKeyLoginUserTokenT);
                    redisClientUtils.setObject(RedisKeys.localTokenKey(userT.getPhone()),aKeyLoginUserTokenT,Integer.valueOf(redisAKeyLoginTokenCacheTime));
                }
            }
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
            ParameterTool.writeErrorResponse(response);
        }
        return null;
    }


    @Override
    public ModelAndView aKeyLoginVerifyIdentity(Map<String, Object> map) {
        HttpServletResponse response = (HttpServletResponse) map.get("response");
        //账号
        String account = MapUtils.getString(map,"account","");
        //类型   type ：1代表一键登录    2代表手机号验证码登录   预留字段   目前只支持1，2    方便以后新增类型扩充
        int type = MapUtils.getIntValue(map,"type",-1);
        //参数校验，account+type均不为空，且type=1或2
        if(StringUtils.isEmpty(account) || (type != 1 && type != 2)){
            ParameterTool.writeErrorResponse(response,-5,"缺少必要参数或所传参数非枚举值！");
            return null;
        }

        //查询手机号对应的用户数据
        UserT userT = loginDao.getUserByUserName(account);
        if(null == userT){
            List<UserT> userTS =  loginDao.getUserByPhone(account);
            if(CollectionUtils.isNotEmpty(userTS) ){
                userT = userTS.get(0);
            }
        }
        if(null != userT){
            Integer userType = userT.getType();
            if(2 == userType){
                ParameterTool.writeResponse(response,2,"");
                return null;
            }
        }
        ParameterTool.writeSuccessResponse(response);
        return null;
    }


    @Override
    @Transactional
    public ModelAndView perfectAccountMessage(String paramStr, HttpServletRequest request,
                                  HttpServletResponse response) throws Exception {
        log.info("perfectAccountMessage.aspx接口入参paramStr："+paramStr);
        //1.提取参数信息
        PerfectAccountMessageRequest perfectAccountMessageRequest = JSON.parseObject(paramStr, PerfectAccountMessageRequest.class);
        //2.校验参数是否必填
        Long userId = perfectAccountMessageRequest.getUserId();
        String contact = perfectAccountMessageRequest.getContact();
        Integer userLabel = perfectAccountMessageRequest.getUserLabel();
        String email = perfectAccountMessageRequest.getEmail();
        String referralCode = perfectAccountMessageRequest.getReferralCode();
        if(userId == -1 || userLabel == -1 || StringUtils.isEmpty(contact)){
            ParameterTool.writeErrorResponse(response, -5);
            return null;
        }
        //更新用户信息
        UserT user = userTDao.selectById(userId);
        UserT userT = new UserT();
        userT.setId(userId);
        userT.setContact(contact);
        userT.setEmail(email);
        if(StringUtils.isEmpty(user.getReferralCode())){
            userT.setReferralCode(referralCode);
        }
        userT.setIsInitInfo(1);
        userTDao.updateUserMsgById(userT);
        //更新用户身份标签信息
        UserLabel label = userLabelMapper.getLabel(userT.getId());
        if (null != label) {
            label.setLaberType(userLabel);
            label.setIsRead(1);
            label.setUpdateTime(LocalTimeUtil.getRealCurrentTime());
            label.setUpdator(userT.getId());
            userLabelMapper.updateByPrimaryKeySelective(label);
        } else {
            label = new UserLabel();
            label.setLaberType(userLabel);
            label.setUserId(userT.getId());
            label.setFlag(0);
            label.setCreator(userT.getId());
            label.setCreateTime(LocalTimeUtil.getRealCurrentTime());
            label.setIsRead(1);
            userLabelMapper.insert(label);
        }
        //根据邀请码 添加邀请用户关系

        inviteUserService.addInsertByCode(userId,user.getPhone(),referralCode);
        ParameterTool.writeSuccessResponse(response);
        return null;
    }


    @Override
    public ModelAndView getWhiteList(Map<String, Object> map){
        HttpServletResponse response = (HttpServletResponse) map.get("response");
        int pageSize = MapUtils.getIntValue(map,"pageSize",1);
        int pageNumber = MapUtils.getIntValue(map,"pageNumber",20);
        PageHelper.startPage(pageNumber, pageSize, true);
        List<Map<String,Object>>  orderTList = serviceStationDao.getWhiteList(map);
        PageInfo pageInfo = new PageInfo<>(orderTList);
        net.sf.json.JSONObject obj = new net.sf.json.JSONObject();
        obj.put("status", 0);
        obj.put("msg", "查询成功");
        Map<String,Object> returnMap = new HashMap<>();
        returnMap.put("list",pageInfo.getList());
        obj.put("data", returnMap);
        ParameterTool.writeResponse(response, obj.toString());
        return null;
    }
}
